package org.wltea.analyzer.seg;

import org.wltea.analyzer.Context;
import org.wltea.analyzer.Lexeme;
import org.wltea.analyzer.help.CharacterHelper;

public class DefaultSegmenter implements ISegmenter {

	private static int FLAG_SEPRATOR = 0x00000001;
	private static int FLAG_CJK = 0x00000010;
	private static int FLAG_LETTER = 0x00000100;
	private static int FLAG_NUM = 0x00001000;
	private static int FLAG_CONNECTOR = 0x00010000;
	private static int FLAG_WHITE = 0x00100000;

	/*
	 * 词元的开始位置， 同时作为子分词器状态标识 当start > -1 时，标识当前的分词器正在处理字符
	 */
	private int start;
	/*
	 * 记录词元结束位置 end记录的是在词元中最后一个出现的Letter但非Sign_Connector的字符的位置
	 */
	private int end;

	/*
	 * 字母起始位置
	 */
	private int letterStart;

	/*
	 * 字母结束位置
	 */
	private int letterEnd;

	private int numberStart;

	private int numberEnd;

	private char[] segmentBuff;

	private final DictMatchHandler dictMatchHandler = new DictMatchHandler();

	private int charFlag;

	private int hisCharFlag;

	public DefaultSegmenter() {
		start = -1;
		end = -1;
		letterStart = -1;
		letterEnd = -1;
		numberStart = -1;
		numberEnd = -1;
	}

	@Override
	public void nextLexeme(char[] segmentBuff, Context context) {
		this.segmentBuff = segmentBuff;
		char input = segmentBuff[context.getCursor()];
		boolean bufferLockFlag = this.process(input, context);
		// 判断是否锁定缓冲区
		if (bufferLockFlag) {
			context.lockBuffer(this);
		} else {
			// 对缓冲区解锁
			context.unlockBuffer(this);
		}
	}

	private boolean isAcceptedNotCJKChar() {
		return charFlag != FLAG_SEPRATOR && charFlag != FLAG_WHITE
				&& charFlag != FLAG_CJK;
	}

	private void processCJK(char[] segmentBuff, Context context) {
		if (charFlag == FLAG_CJK) {
			dictMatchHandler.handleCJK(segmentBuff, context);
		}
	}

	private void processLetter(char[] segmentBuff, Context context) {
		if (charFlag == FLAG_LETTER) {
			if (letterStart < 0) {
				// 记录起始指针的位置,标明分词器进入处理状态
				letterStart = context.getCursor();
				letterEnd = letterStart;
			} else {
				// 记录当前指针位置为结束位置
				letterEnd = context.getCursor();
			}
		} else if (letterEnd >= 0) {
			// 生成已切分的词元
			if (isAcceptedNotCJKChar() || start < letterStart) {
				dictMatchHandler.handleMix(segmentBuff, letterStart, letterEnd
						- letterStart + 1, context, Lexeme.TYPE_LETTER, true);
			}
			// 设置当前分词器状态为“待处理”
			letterStart = -1;
			letterEnd = -1;
		}
	}

	private void processNum(char[] segmentBuff, Context context) {
		if (charFlag == FLAG_NUM) {
			if (numberStart < 0) {
				// 记录起始指针的位置,标明分词器进入处理状态
				numberStart = context.getCursor();
				numberEnd = numberStart;
			} else {
				// 记录当前指针位置为结束位置
				numberEnd = context.getCursor();
			}
		} else if (numberEnd >= 0) {
			// 生成已切分的词元
			if (isAcceptedNotCJKChar() || start < numberStart) {
				dictMatchHandler.handleMix(segmentBuff, numberStart, numberEnd
						- numberStart + 1, context, Lexeme.TYPE_NUM, true);
			}
			// 设置当前分词器状态为“待处理”
			numberStart = -1;
			numberEnd = -1;
		}
	}

	private int getMixLexemeType() {
		if (hisCharFlag == FLAG_CONNECTOR) {
			return Lexeme.TYPE_CONNECTOR;
		}
		if ((hisCharFlag & FLAG_CONNECTOR) > 0) {
			return Lexeme.TYPE_CONNECTOR_MIX;
		} else if ((hisCharFlag & FLAG_NUM) > 0
				&& (hisCharFlag & FLAG_LETTER) > 0) {
			return Lexeme.TYPE_LETTER_MIX;
		} else if ((hisCharFlag & FLAG_LETTER) > 0) {
			return Lexeme.TYPE_LETTER;
		} else if ((hisCharFlag & FLAG_NUM) > 0) {
			return Lexeme.TYPE_NUM;
		}
		throw new RuntimeException("invalid hisCharFlag:" + hisCharFlag);
	}

	private void processMix(char[] segmentBuff, Context context) {
		if (isAcceptedNotCJKChar()) {
			if (start == -1) {
				// 记录起始指针的位置,标明分词器进入处理状态
				start = context.getCursor();
				end = start;
			} else {
				end = context.getCursor();
				if (context.getCursor() < context.getAvailable() - 2) {
					if (CharacterHelper.isLetterConnector(segmentBuff[context
							.getCursor() + 1])) {
						// 判断是否属于词典
						dictMatchHandler.handleMixDictMatch(segmentBuff, start,
								end - start + 1, context, getMixLexemeType());
					}
				}
			}
		} else if (start >= 0) {
			// 生成已切分的词元
			dictMatchHandler.handleMix(segmentBuff, start, end - start + 1,
					context, getMixLexemeType(), false);
			// 设置当前分词器状态为“待处理”
			start = -1;
			end = -1;
		}
	}

	private void processSeprator(char[] segmentBuff, Context context) {
		if (charFlag == FLAG_SEPRATOR) {
			dictMatchHandler.handleSeprator(segmentBuff, context);
		}
	}

	private void processLastChar(char[] segmentBuff, Context context) {
		if (context.getCursor() == context.getAvailable() - 1) {
			if (start != -1 && end != -1) {
				// 生成已切分的词元
				if (start < letterStart) {
					dictMatchHandler.handleMix(segmentBuff, letterStart,
							letterEnd - letterStart + 1, context,
							Lexeme.TYPE_LETTER, true);
				}
				if (start < numberStart) {
					dictMatchHandler.handleMix(segmentBuff, numberStart,
							numberEnd - numberStart + 1, context,
							Lexeme.TYPE_LETTER, true);
				}
				dictMatchHandler.handleMix(segmentBuff, start, end - start + 1,
						context, getMixLexemeType(), false);
			}
			dictMatchHandler.handleSeprator(segmentBuff, context);
			// 设置当前分词器状态为“待处理”
			start = -1;
			end = -1;
			numberStart = -1;
			numberEnd = -1;
			letterStart = -1;
			letterEnd = -1;
		}
	}

	/**
	 * @param input
	 * @param context
	 * @return
	 */
	private boolean process(char input, Context context) {
		boolean needLock = false;
		if (CharacterHelper.isEnglishLetter(input)) {
			charFlag = FLAG_LETTER;
			hisCharFlag |= charFlag;
		} else if (CharacterHelper.isCJKCharacter(input)) {
			charFlag = FLAG_CJK;
		} else if (CharacterHelper.isArabicNumber(input)) {
			charFlag = FLAG_NUM;
			hisCharFlag |= charFlag;
		} else if (CharacterHelper.isLetterConnector(input)) {
			if (input == '.') {
				int pos = context.getCursor();
				if (pos >= context.getAvailable() - 1
						|| (!CharacterHelper.isEnglishLetter(context
								.getChar(pos + 1)) && !CharacterHelper
								.isArabicNumber(context.getChar(pos + 1)))) {
					charFlag = FLAG_SEPRATOR;
				} else {
					charFlag = FLAG_CONNECTOR;
					hisCharFlag |= charFlag;
				}
			} else {
				charFlag = FLAG_CONNECTOR;
				hisCharFlag |= charFlag;
			}
		} else if (input == ' ') {
			charFlag = FLAG_WHITE;
		} else {
			charFlag = FLAG_SEPRATOR;
		}
		// System.out.println("input=" + input + ",start=" + start + ",end=" +
		// end
		// + ",letterstart=" + letterStart + ",letterend=" + letterEnd);
		processLetter(segmentBuff, context);
		processNum(segmentBuff, context);
		processMix(segmentBuff, context);
		processCJK(segmentBuff, context);
		processSeprator(segmentBuff, context);
		processLastChar(segmentBuff, context);
		if (charFlag == FLAG_CJK || charFlag == FLAG_WHITE
				|| charFlag == FLAG_SEPRATOR) {
			hisCharFlag = 0;
		}
		// 判断是否锁定缓冲区
		if (start == -1 && end == -1 && letterStart == -1 && letterEnd == -1
				&& numberStart == -1 && numberEnd == -1) {
			// 对缓冲区解锁
			needLock = false;
		} else {
			needLock = true;
		}
		if (!needLock) {
			needLock = dictMatchHandler.needLocked();
		}
		return needLock;
	}

	@Override
	public void reset() {
		start = -1;
		end = -1;
		letterStart = -1;
		letterEnd = -1;
		numberStart = -1;
		numberEnd = -1;
		dictMatchHandler.reset();
	}

}
